from .UrlsTableInfo import UrlsTableInfo
from . import varint

def conver_bytes_to_int(num_bytes: bytes) -> int:
    return int.from_bytes(num_bytes, byteorder='big', signed=False)

class Sqlite3Parser:
    def __init__(self, data):
        self.data = data
        self.pagesize = 0
        self.pagecount = 0
        self.codetype = ''

        self.parse_pagesize()
        self.parse_pagecount()
        self.parse_codetype()

    def parse_pagesize(self):
        self.pagesize = conver_bytes_to_int(self.data[16:18])

    def parse_pagecount(self):
        self.pagecount = conver_bytes_to_int(self.data[28:32])

    def parse_codetype(self):
        flag = conver_bytes_to_int(self.data[56:60])

        if flag == 1:
            self.codetype = 'utf-8'
        elif flag == 2:
            self.codetype = 'utf-16le'
        elif flag == 3:
            self.codetype = 'utf-16be'
        else:
            self.codetype = ''

    def page_address(self, pageindex):
        return (pageindex - 1) * self.pagesize

    def parse_urls_page_end(self, rootpage_address):
        if b'\x05' != self.data[rootpage_address:rootpage_address+1]:
            return 0
        end_bytes = self.data[rootpage_address+8:rootpage_address+12]
        return int.from_bytes(end_bytes, byteorder='big', signed=False)

    def parse_page_freeblocks(self, pageindex):
        address = self.page_address(pageindex)
        page_bytes = self.data[address:address+self.pagesize]
        if b'\x0d' != page_bytes[0:1]:
            return []

        freeblock_address = conver_bytes_to_int(page_bytes[1:3])

        address_list = []
        # 叶子叶头部最少12字节，偏移不应超过页大小
        while freeblock_address in range(12, self.pagesize):
            address_list.append(address+freeblock_address)
            freeblock_address = conver_bytes_to_int(page_bytes[freeblock_address:freeblock_address+2])

        return address_list

    def parse_free_block(self, block_address, table_info: UrlsTableInfo):
        '''
        不确定长度，取其中部分足够长的数据做处理
        已知所要读取的表
        删除之前:
            cellsize 不超过页大小，1-2位
            rowid, 不超过2097151， 1-3位
            headersize必只占据一位, 0～127，单条不超过页大小, 2^14 >> 4096, 不超过63个字段，当前urls表为7
        三者和X占据3-6个字节
            3: 删除后从cellsize位置覆盖到至多type1位置
            4: >>> Fit
            5: 首个可变长数据占据一位，值为type_numer * (1 ~ 2)
            6：残缺的rowid，完整的headersize, type_number 个可变长度数据
        尝试读取 type_number + 2个数据
        '''
        def sum_list_last(numlist, lastnum):
            if len(numlist) <= lastnum:
                return sum(numlist)
            tmp = numlist[len(numlist)-lastnum:]
            return sum(tmp)

        tmp_bytes = self.data[block_address:block_address+self.pagesize]
        cellsize = conver_bytes_to_int(tmp_bytes[2:4])
        type_values = []  # 保存各字段占用大小
        type_sizes = []  # 保存各字段大小本身占用大小
        already_read_size = 4  # 已读取分析的字段长度，初始为4，下个自由块偏移与当前自由块大小，各占2字节
        max_read = table_info.type_number + 2
        while True:
            type_i_size, read_size = varint.decode_bytes(tmp_bytes[already_read_size])
            if read_size > 2 or read_size == 0 or len(type_values) == max_read:
                break
            type_values.append(type_i_size)
            type_sizes.append(read_size)
            already_read_size += read_size

        # 只读到了type_number -1个数据，在id > 2^14或者被覆盖时可能存在此情况
        # X = 3
        if len(type_values) == table_info.type_number - 1:
            analyzed_size = 4 + sum(type_sizes) + sum(type_values)
            if cellsize > analyzed_size:
                type_1_value = cellsize - analyzed_size
                type_1_size = varint.varint_lenth(type_1_value)
                type_sizes.insert(0, type_1_size)
                type_values.insert(0, type_1_value)
        # < type_number
        elif len(type_sizes) < table_info.type_number:
            pass
        # X = 6
        elif type_sizes[0:2] == [1, 1] and cellsize == 6 + sum_list_last(type_sizes, table_info.type_number) \
                + sum_list_last(type_values, table_info.type_number):
            pass
        # X = 5
        elif type_sizes[0] == 1 and cellsize == 5 + sum:
            pass
        # X = 4
        elif sum(type_values[0:table_info.type_number]) + sum(type_sizes[0:table_info.type_number]) + 4 == cellsize:
            pass
        else:  # type_list长度小于type_number -1
            pass

    def parse_normal_block(self, pageindex, table_info: UrlsTableInfo):
        address = self.page_address(pageindex)
        page_bytes = self.data[address:address+self.pagesize]
        if b'\x0d' != page_bytes[0:1]:
            return ''

        first_block_address = conver_bytes_to_int(page_bytes[5:7])
        print(first_block_address)
        tmp_l = []
        tmp_l_s = []

        while True:
            try:
                if first_block_address + sum(tmp_l_s) >= self.pagesize:
                    break
                value, value_size = varint.decode_bytes(page_bytes[first_block_address+sum(tmp_l_s):])
            except:
                break
            if not value and value_size > 2:
                break
            tmp_l.append(value)
            tmp_l_s.append(value_size)
        print(tmp_l)

    def parse_cell_header(self, block_address):
        pass


'''
            if len(type_list) >= 6:

                if sum_list_last(type_list, 7) +  already_read_size == cellsize:
                    pass

                if sum_list_last(type_list, 7) + already_read_size > cellsize:
                    # 读取过界，回退
                    already_read_size -= read_size
                    type_list.pop()

                    type_1_size = cellsize - already_read_size - sum_list_last(type_list, 6)
                    if len(type_list) > 6:
                        type_list = type_list[len(type_list)-6:]
                    type_list.insert(0, type_1_size)
'''
